/**
 * huize Service Inc
 * All Rights Reserved @2018
 */
package com.hzins.zhike.okhttp3.simple;

import lombok.extern.slf4j.Slf4j;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.Serializable;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;

/**
 * 描述:
 *
 * @author tianyuliang
 * @version $Id: InitOkHttpClient.java, v0.1 2022/4/14
 */
@Slf4j
public class InitOkHttpClient implements Serializable {

    private static final long serialVersionUID = 1L;

    private volatile OkHttpClient okHttpClient = null;

    private InitOkHttpClient() {
        if (InitOkHttpParam.EXECUTOR == null) {
            throw new IllegalArgumentException("OkHttpClient线程池不能为空! 需要自定义设置!");
        }
        Dispatcher dispatcher = new Dispatcher(InitOkHttpParam.EXECUTOR);
        dispatcher.setMaxRequests(InitOkHttpParam.MAX_REQUEST);
        dispatcher.setMaxRequestsPerHost(InitOkHttpParam.MAX_REQUEST_PRE_HOST);
        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().dispatcher(dispatcher);
        clientBuilder.readTimeout(InitOkHttpParam.READ_TIME_OUT, TimeUnit.MILLISECONDS);
        clientBuilder.connectTimeout(InitOkHttpParam.CONNECT_TIME_OUT, TimeUnit.MILLISECONDS);
        clientBuilder.writeTimeout(InitOkHttpParam.WRITE_TIME_OUT, TimeUnit.MILLISECONDS);
        clientBuilder.sslSocketFactory(createSSLSocketFactory());
        clientBuilder.hostnameVerifier(new SimpleHostnameVerifier());
        clientBuilder.addInterceptor(new RetryInterceptor(InitOkHttpParam.RETRY_COUNT, InitOkHttpParam.RETRY_INTERVAL));

        okHttpClient = clientBuilder.build();
        log.info("okHttpClient 初始化完成!");
    }

    /**
     * 支持HTTPS请求，跳过证书认证
     */
    private static SSLSocketFactory createSSLSocketFactory() {
        TrustManager[] trustManagers = new TrustManager[]{new SSLSocketX509TrustManager()};
        SSLSocketFactory sslSocketFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustManagers, new SecureRandom());
            sslSocketFactory = sc.getSocketFactory();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            log.error("配置SSL错误. err={}", e.getMessage(), e);
        }
        return sslSocketFactory;
    }

    public static OkHttpClient getInstance() {
        return SingletonHolder.INSTANCE.okHttpClient;
    }

    public Object readResolve() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static InitOkHttpClient INSTANCE = new InitOkHttpClient();
    }

}